#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "network.h"
#include "tools.h"

NetWork* nw;

NetWork* pasv(void)
{
	char buf[256] = {};
	send_str(nw, "PASV\n", strlen("PASV\n"));
	recv_str(nw, buf, sizeof(buf));

	unsigned char ip1, ip2, ip3, ip4, port1, port2;
	sscanf(strchr(buf, '(')+1, "%hhu, %hhu, %hhu, %hhu, %hhu, %hhu", &ip1, &ip2, &ip3, &ip4, &port1, &port2);
	//char new_ip[30] = {};
	sprintf(buf, "%hhu.%hhu.%hhu.%hhu", ip1, ip2, ip3, ip4);
	return open_network('c', SOCK_STREAM, buf, port1*256+port2);
}

void order_ls()
{
	char buf[256] = {};
	NetWork* new_nw = pasv();

	send_str(nw, "LIST -al\n", strlen("LIST -al\n"));
	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);

	int ret = 0;
	while(ret = recv_str(new_nw, buf, sizeof(buf)))
	{
		printf("%s", buf);
	}
	close_network(new_nw);

	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);
}

void order_cd()
{
	char name[30] = {};
	scanf("%s", name);

	char buf[256] = {};
	sprintf(buf, "CWD %s\n", name);
	send_str(nw, buf, strlen(buf));
	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);
}

void order_get()
{
	char name[30] = {};
	scanf("%s", name);

	char buf[256] = {};
	NetWork* new_nw = pasv();
	
	sprintf(buf, "RETR %s\n", name);
	send_str(nw, buf, strlen(buf));
	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);

	int fd = open(name, O_CREAT|O_WRONLY, 0644);
	int ret = 0;
	while(ret = recv_str(new_nw, buf, sizeof(buf)))
	{
		write(fd, buf, ret);
	}
	close(fd);
	close_network(new_nw);

	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);
}

void order_put()
{
	char name[30] = {};
	scanf("%s", name);

	char buf[256] = {};
	NetWork* new_nw = pasv();
	
	sprintf(buf, "STOR %s\n", name);
	send_str(nw, buf, strlen(buf));
	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);

	int fd = open(name, O_RDONLY);
	int ret = 0;
	while(ret = read(fd, buf, sizeof(buf)))
	{
		send_str(new_nw, buf, ret);
	}
	close(fd);
	close_network(new_nw);

	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);
}

void order_bye(void)
{
	char buf[256] = {};
	send_str(nw, "QUIT\n", strlen("QUIT\n"));
	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);
}

void get_order(void)
{
	char order[10] = {};
	while(true)
	{
		printf("ftp> ");
		scanf("%s", order);
		if(0 == strcmp("ls", order)) order_ls();
		else if(0 == strcmp("cd", order)) order_cd();
		else if(0 == strcmp("get", order)) order_get();
		else if(0 == strcmp("put", order)) order_put();	
		else if(0 == strcmp("bye", order))
		{
			order_bye();
			break;
		}
		else puts("error order");
	}
}

void enter(char* ip)
{
	nw = open_network('c', SOCK_STREAM, ip, 21);
	char buf[256] ={};
	printf("Connect to %s\n", ip);
	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);
	
	char name[20] = {};
	printf("Name(%s):", ip);
	get_str(name, 20);
	sprintf(buf, "USER %s\n", name);
	send_str(nw, buf, strlen(buf));
	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);

	char pass[20] = {};
	printf("Password:");
	get_passwd(pass, false, 20);
	sprintf(buf, "PASS %s\n", pass);
	send_str(nw, buf, strlen(buf));
	recv_str(nw, buf, sizeof(buf));
	printf("%s", buf);
}

int main(int argv, char* argc[])
{
	enter(argc[1]);
	get_order();
}
